package pe.com.casadesign.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.stereotype.Repository;

import pe.com.casadesign.dao.ProductoDAO;
import pe.com.casadesign.domain.Componente;
import pe.com.casadesign.domain.ListaComponente;
import pe.com.casadesign.domain.ListaProducto;
import pe.com.casadesign.domain.NivelColor;
import pe.com.casadesign.domain.NivelMaterial;
import pe.com.casadesign.domain.NivelProducto;
import pe.com.casadesign.domain.NivelTipo;
import pe.com.casadesign.domain.Producto;
import pe.com.casadesign.domain.Proveedor;
import pe.com.casadesign.domain.Tienda;

/**
 * Implementacion de ProductoDAO.
 * 
 * @author Pedro Vera
 * 
 */
@Repository
public class ProductoDAOImpl implements ProductoDAO {
private static final Logger logger = LoggerFactory.getLogger(ProductoDAOImpl.class);
	
	// Nombre Procedimientos Almacenados
	private static String SP_LISTAR_PRODUCTO = "SP_LISTAR_PRODUCTO";
	private static String SP_OBTENER_PRODUCTO = "SP_OBTENER_PRODUCTO";
	private static String SP_REGISTRAR_PRODUCTO = "SP_REGISTRAR_PRODUCTO";
	private static String SP_MODIFICAR_PRODUCTO = "SP_MODIFICAR_PRODUCTO";
	private static String SP_ELIMINAR_PRODUCTO = "SP_ELIMINAR_PRODUCTO";
	private static String SP_OBTENER_PRODUCTO_CODPROV = "SP_OBTENER_PRODUCTO_CODPROV";
	
	private static String SP_REGISTRAR_COMPONENTE_PRODUCTO = "SP_REGISTRAR_COMPONENTE_PRODUCTO";
	private static String SP_LIMPIAR_COMPONENTE_PRODUCTO = "SP_LIMPIAR_COMPONENTE_PRODUCTO";
	
	// Parametros de Entrada
	private static String PARAM_CODPRODUCTO = "p_codproducto";
	private static String PARAM_DESCRIPCION = "p_descripcion";
	private static String PARAM_PRECIOVENTAMINIMO = "p_precioventaminimo";
	private static String PARAM_PRECIOVENTAMAXIMO = "p_precioventamaximo";
	private static String PARAM_ALTO = "p_alto";
	private static String PARAM_ANCHO = "p_ancho";
	private static String PARAM_LARGO = "p_largo";
	private static String PARAM_UNIDADMEDIDA = "p_unidadmedida";
	private static String PARAM_CODNIVELPROD = "p_codnivelprod";
	private static String PARAM_CODNIVELTIPO = "p_codniveltipo";
	private static String PARAM_CODNIVELMATERIAL = "p_codnivelmaterial";
	private static String PARAM_CODNIVELCOLOR = "p_codnivelcolor";
	private static String PARAM_CODPROVEEDOR = "p_codproveedor";
	private static String PARAM_CODPRODUCTOPROVEEDOR = "p_codproductoproveedor";
	private static String PARAM_COMPONENTES = "p_componentes";
	private static String PARAM_OBSERVACIONES = "p_observaciones";
	private static String PARAM_ESTADO = "p_estado";
	private static String PARAM_CODTIENDA = "p_codtienda";
	private static String PARAM_CONSIGNACION = "p_consignacion";
	private static String PARAM_UNIONPRODUCTO = "p_unionproducto";
	//private static String PARAM_FECHAREGISTRO = "P_FECHAREGISTRO";
	
	private static String PARAM_COMPONENTEPRODUCTO_CODPRODUCTO = "p_codproducto";
	private static String PARAM_COMPONENTEPRODUCTO_CODCOMPONENTE = "p_codcomponente";
	private static String PARAM_COMPONENTEPRODUCTO_CODPRODUCTOUNION = "p_codproductounion";
	
	// Parametros de Salida
	private static String CODPRODUCTO = "CODPRODUCTO";
	private static String DESCRIPCION = "DESCRIPCION";
	private static String PRECIOVENTAMINIMO = "PRECIOVENTAMINIMO";
	private static String PRECIOVENTAMAXIMO = "PRECIOVENTAMAXIMO";
	private static String ALTO = "ALTO";
	private static String ANCHO = "ANCHO";
	private static String LARGO = "LARGO";
	private static String UNIDADMEDIDA = "UNIDADMEDIDA";
	private static String CODNIVELPROD = "CODNIVELPROD";
	private static String CODNIVELTIPO = "CODNIVELTIPO";
	private static String CODNIVELMATERIAL = "CODNIVELMATERIAL";
	private static String CODNIVELCOLOR = "CODNIVELCOLOR";
	private static String CODPROVEEDOR = "CODPROVEEDOR";
	private static String CODPRODUCTOPROVEEDOR = "CODPRODUCTOPROVEEDOR";
	private static String COMPONENTES = "COMPONENTES";
	private static String CANTIDADDISPONIBLE = "CANTIDADDISPONIBLE";
	private static String ESTADO = "ESTADO";
	private static String OBSERVACIONES = "OBSERVACIONES";
	private static String FECHAREGISTRO = "FECHAREGISTRO";
	private static String CONSIGNACION = "CONSIGNACION";
	private static String UNIONPRODUCTO = "UNIONPRODUCTO";
	
	private static String NIVEL_PRODUCTO_DESCRIPCION = "DESNIVELPRODUCTO";
	private static String NIVEL_TIPO_DESCRIPCION = "DESNIVELTIPO";
	private static String NIVEL_MATERIAL_DESCRIPCION = "DESNIVELMATERIAL";
	private static String NIVEL_COLOR_DESCRIPCION = "DESNIVELCOLOR";
	
	private static String PROVEEDOR_RAZONSOCIAL = "RAZONSOCIAL";
	
	private static String COMPONENTE_CODIGO = "CODCOMPONENTE";
	private static String COMPONENTE_DESCRIPCION = "DESCRIPCION";
	private static String COMPONENTE_ESTADO = "ESTADO";
	private static String COMPONENTE_FECHAREGISTRO = "FECHAREGISTRO";
	private static String COMPONENTE_CODPRODUCTOUNION = "CODPRODUCTOUNION";
	private static String COMPONENTE_DESCRIPCIONPRODUCTOUNION = "DESCRIPCIONPRODUCTOUNION";
	
	private static String LISTADO = "LISTADO";
	private static String LISTADO_COMPONENTES = "LISTADO_COMPONENTES";
	
	private static String TOTAL_FILAS_AFECTADAS = "#update-count-1";
	
	private JdbcTemplate jdbcTemplate;

	@Autowired
    public void setDataSource(DataSource dataSource)
    {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
	
	@Override
	public ListaProducto listarProducto(Producto producto) {
		logger.info("listarProducto");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_PRODUCTO).
	    						  returningResultSet(LISTADO, new RowMapper<Producto>(){
									@Override
									public Producto mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setDescripcion(rs.getString(DESCRIPCION));
								        producto.setPrecioVentaMinimo(rs.getDouble(PRECIOVENTAMINIMO));
								        producto.setPrecioVentaMaximo(rs.getDouble(PRECIOVENTAMAXIMO));
								    	producto.setAlto(rs.getDouble(ALTO));
								    	producto.setAncho(rs.getDouble(ANCHO));
								    	producto.setLargo(rs.getDouble(LARGO));
								    	producto.setUnidadMedida(rs.getString(UNIDADMEDIDA));
								    	producto.setObservaciones(rs.getString(OBSERVACIONES));
								    	
								    	NivelProducto nivelProducto = new NivelProducto();
								    	nivelProducto.setCodigo(rs.getInt(CODNIVELPROD));
								    	nivelProducto.setDescripcion(rs.getString(NIVEL_PRODUCTO_DESCRIPCION));
								    	producto.setNivelProducto(nivelProducto);
								    	
								    	NivelTipo nivelTipo = new NivelTipo();
								    	nivelTipo.setCodigo(rs.getInt(CODNIVELTIPO));
								    	nivelTipo.setDescripcion(rs.getString(NIVEL_TIPO_DESCRIPCION));
								    	producto.setNivelTipo(nivelTipo);
								    	
								    	NivelMaterial nivelMaterial =  new NivelMaterial();
								    	nivelMaterial.setCodigo(rs.getInt(CODNIVELMATERIAL));
								    	nivelMaterial.setDescripcion(rs.getString(NIVEL_MATERIAL_DESCRIPCION));
								    	producto.setNivelMaterial(nivelMaterial);
								    	
								    	NivelColor nivelColor = new NivelColor();
								    	nivelColor.setCodigo(rs.getInt(CODNIVELCOLOR));
								    	nivelColor.setDescripcion(rs.getString(NIVEL_COLOR_DESCRIPCION));
								    	producto.setNivelColor(nivelColor);
								    	
								    	Proveedor proveedor = new Proveedor();
								    	proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								    	proveedor.setRazonSocial(rs.getString(PROVEEDOR_RAZONSOCIAL));
								    	producto.setProveedor(proveedor);
								    	
								    	producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								    	producto.setComponentes(rs.getString(COMPONENTES));
								        
								        producto.setEstado(rs.getString(ESTADO));
								        producto.setConsignacion(rs.getString(CONSIGNACION));
								        producto.setUnionProducto(rs.getString(UNIONPRODUCTO));
								        producto.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return producto;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODNIVELPROD, producto.getNivelProducto().getCodigo())
	    								.addValue(PARAM_CODNIVELTIPO, producto.getNivelTipo().getCodigo())
	    								.addValue(PARAM_CODNIVELMATERIAL, producto.getNivelMaterial().getCodigo())
	    								.addValue(PARAM_CODNIVELCOLOR, producto.getNivelColor().getCodigo())
	    								.addValue(PARAM_CODPRODUCTOPROVEEDOR, producto.getCodProductoProveedor())
	    								.addValue(PARAM_UNIONPRODUCTO, producto.getUnionProducto())
	    								.addValue(PARAM_DESCRIPCION, producto.getDescripcion())
	    								.addValue(PARAM_ESTADO, producto.getEstado()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Producto> listaProducto= (List<Producto>)data.get(LISTADO);
        
		// Instanciando objeto ListaProducto
		ListaProducto listaProductoResultado = new ListaProducto();
        // Estableciendo resultado al objeto listaProductoResultado
		listaProductoResultado.setLista(listaProducto);
        
        if (logger.isDebugEnabled() && listaProductoResultado != null)
        {
            logger.debug("size=" + listaProductoResultado.size());
        }
        return listaProductoResultado;
	}

	@Override
	public Producto obtenerProducto(Producto producto, Tienda tienda) {
		logger.info("obtenerProducto");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_OBTENER_PRODUCTO).
	    						  returningResultSet(LISTADO, new RowMapper<Producto>(){
									@Override
									public Producto mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
										final Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setDescripcion(rs.getString(DESCRIPCION));
								        producto.setPrecioVentaMinimo(rs.getDouble(PRECIOVENTAMINIMO));
								        producto.setPrecioVentaMaximo(rs.getDouble(PRECIOVENTAMAXIMO));
								    	producto.setAlto(rs.getDouble(ALTO));
								    	producto.setAncho(rs.getDouble(ANCHO));
								    	producto.setLargo(rs.getDouble(LARGO));
								    	producto.setUnidadMedida(rs.getString(UNIDADMEDIDA));
								    	producto.setObservaciones(rs.getString(OBSERVACIONES));
								    	
								    	NivelProducto nivelProducto = new NivelProducto();
								    	nivelProducto.setCodigo(rs.getInt(CODNIVELPROD));
								    	nivelProducto.setDescripcion(rs.getString(NIVEL_PRODUCTO_DESCRIPCION));
								    	producto.setNivelProducto(nivelProducto);
								    	
								    	NivelTipo nivelTipo = new NivelTipo();
								    	nivelTipo.setCodigo(rs.getInt(CODNIVELTIPO));
								    	nivelTipo.setDescripcion(rs.getString(NIVEL_TIPO_DESCRIPCION));
								    	producto.setNivelTipo(nivelTipo);
								    	
								    	NivelMaterial nivelMaterial =  new NivelMaterial();
								    	nivelMaterial.setCodigo(rs.getInt(CODNIVELMATERIAL));
								    	nivelMaterial.setDescripcion(rs.getString(NIVEL_MATERIAL_DESCRIPCION));
								    	producto.setNivelMaterial(nivelMaterial);
								    	
								    	NivelColor nivelColor = new NivelColor();
								    	nivelColor.setCodigo(rs.getInt(CODNIVELCOLOR));
								    	nivelColor.setDescripcion(rs.getString(NIVEL_COLOR_DESCRIPCION));
								    	producto.setNivelColor(nivelColor);
								    	
								    	Proveedor proveedor = new Proveedor();
								    	proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								    	proveedor.setRazonSocial(rs.getString(PROVEEDOR_RAZONSOCIAL));
								    	producto.setProveedor(proveedor);
								    	
								    	producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								    	producto.setComponentes(rs.getString(COMPONENTES));
								        
								    	producto.setCantidadDisponible(rs.getInt(CANTIDADDISPONIBLE));
								    	
								        producto.setEstado(rs.getString(ESTADO));
								        producto.setConsignacion(rs.getString(CONSIGNACION));
								        producto.setUnionProducto(rs.getString(UNIONPRODUCTO));
								        producto.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return producto;
								    }
	    						  }
								 )
								 .returningResultSet(LISTADO_COMPONENTES, new RowMapper<Componente>(){
									@Override
									public Componente mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Componente componente = new Componente();
								        componente.setCodigo(rs.getInt(COMPONENTE_CODIGO));
								        componente.setDescripcion(rs.getString(COMPONENTE_DESCRIPCION));
								        componente.setEstado(rs.getString(COMPONENTE_ESTADO));
								        componente.setFechaRegistro(rs.getDate(COMPONENTE_FECHAREGISTRO).toString());
								        
								        Producto productounion = new Producto();
								        productounion.setCodigo(rs.getInt(COMPONENTE_CODPRODUCTOUNION));
								        productounion.setDescripcion(rs.getString(COMPONENTE_DESCRIPCIONPRODUCTOUNION));
								        componente.setProducto(productounion);
								        
								        return componente;
								    }
	    						  });

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODPRODUCTO, producto.getCodigo())
	    								.addValue(PARAM_CODTIENDA, tienda.getCodigo()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
 		@SuppressWarnings("unchecked")
 		List<Producto> listaProducto= (List<Producto>)data.get(LISTADO);
         
 		// Declarando objeto producto Obtenido
 		Producto productoObtenido = null;
 		
 		if (logger.isDebugEnabled() && listaProducto != null)
        {
            logger.debug("size=" + listaProducto.size());
        }
 		
 		if (listaProducto != null && listaProducto.size()>0){
 			// Obteniendo el primer elemento de la lista de producto
 			productoObtenido = listaProducto.get(0);
 		
	        // Obteniendo lista de componentes generada de ejecutar SP
			@SuppressWarnings("unchecked")
			List<Componente> listaComponente= (List<Componente>)data.get(LISTADO_COMPONENTES);
	        
			// Instanciando objeto ListaComponente
			ListaComponente listaComponenteResultado = new ListaComponente();
	        // Estableciendo resultado al objeto ListaComponente
			listaComponenteResultado.setLista(listaComponente);

			// Asignando lista de componentes al objeto producto creado
			productoObtenido.setListaComponente(listaComponenteResultado);

	        if (logger.isDebugEnabled() && listaComponente != null)
	        {
	            logger.debug("sizeComponentes=" + listaComponente.size());
	        }
 		}
        return productoObtenido;
	}

	@Override
	public boolean registrarProducto(Producto producto) {
		logger.info("registrarProducto");
		
		int resultado = 0;
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate)
	    							  .withProcedureName(SP_REGISTRAR_PRODUCTO);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_DESCRIPCION, producto.getDescripcion())
	    								.addValue(PARAM_PRECIOVENTAMINIMO, producto.getPrecioVentaMinimo())
	    								.addValue(PARAM_PRECIOVENTAMAXIMO, producto.getPrecioVentaMaximo())
	    								.addValue(PARAM_ALTO, producto.getAlto())
	    								.addValue(PARAM_ANCHO, producto.getAncho())
	    								.addValue(PARAM_LARGO, producto.getLargo())
	    								.addValue(PARAM_UNIDADMEDIDA, producto.getUnidadMedida())
	    								.addValue(PARAM_CODNIVELPROD, producto.getNivelProducto().getCodigo())
	    								.addValue(PARAM_CODNIVELTIPO, producto.getNivelTipo().getCodigo())
	    								.addValue(PARAM_CODNIVELMATERIAL, producto.getNivelMaterial().getCodigo())
	    								.addValue(PARAM_CODNIVELCOLOR, producto.getNivelColor().getCodigo())
	    								.addValue(PARAM_CODPROVEEDOR, producto.getProveedor().getCodProveedor())
	    								.addValue(PARAM_CODPRODUCTOPROVEEDOR, producto.getCodProductoProveedor())
	    								.addValue(PARAM_COMPONENTES, producto.getComponentes())
	    								.addValue(PARAM_OBSERVACIONES, producto.getObservaciones())
	    								.addValue(PARAM_CONSIGNACION, producto.getConsignacion())
	    								.addValue(PARAM_UNIONPRODUCTO, producto.getUnionProducto())
	    								.addValue(PARAM_ESTADO, producto.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    resultado += (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    logger.debug("codigo generado:" + data.get(PARAM_CODPRODUCTO));

	    // Obteniendo codigo de producto
	    int codigoProducto = (Integer)data.get(PARAM_CODPRODUCTO);

	    // Estableciendo codigo generado al objeto producto
	    producto.setCodigo(codigoProducto);
	    
	    // Obteniendo lista de componentes a agregar
	    ListaComponente listaComponente = producto.getListaComponente();
	    
	    // Si existen componentes entonces registrarlos
	    if(listaComponente.getLista() != null){
		    // Instanciando variable para llamado de SP
		    SimpleJdbcCall llamarSPComponentes = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_COMPONENTE_PRODUCTO);
	
		    for (Componente componente : listaComponente.getLista()){
			    // Estableciendo parametros de entrada al SP
			    SqlParameterSource parametrosContactos = new MapSqlParameterSource()
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODPRODUCTO, codigoProducto)
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODCOMPONENTE, componente.getCodigo())
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODPRODUCTOUNION, componente.getProducto()==null?null:componente.getProducto().getCodigo());
			    
			    // Establecer parametros y ejecutar SP
			    Map<String,Object> dataComponente = llamarSPComponentes.execute(parametrosContactos);
			    
			    // Obteniendo el total de filas afectadas al ejecutar SP
			    resultado += (Integer) dataComponente.get(TOTAL_FILAS_AFECTADAS);
		    }
	    }
	    
	    return resultado > 0;
	}

	@Override
	public boolean modificarProducto(Producto producto) {
		logger.info("modificarProducto");
		
		int resultado = 0;
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_MODIFICAR_PRODUCTO);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODPRODUCTO, producto.getCodigo())
	    								.addValue(PARAM_DESCRIPCION, producto.getDescripcion())
	    								.addValue(PARAM_PRECIOVENTAMINIMO, producto.getPrecioVentaMinimo())
	    								.addValue(PARAM_PRECIOVENTAMAXIMO, producto.getPrecioVentaMaximo())
	    								.addValue(PARAM_ALTO, producto.getAlto())
	    								.addValue(PARAM_ANCHO, producto.getAncho())
	    								.addValue(PARAM_LARGO, producto.getLargo())
	    								.addValue(PARAM_UNIDADMEDIDA,producto.getUnidadMedida())
	    								.addValue(PARAM_CODNIVELPROD, producto.getNivelProducto().getCodigo())
	    								.addValue(PARAM_CODNIVELTIPO, producto.getNivelTipo().getCodigo())
	    								.addValue(PARAM_CODNIVELMATERIAL, producto.getNivelMaterial().getCodigo())
	    								.addValue(PARAM_CODNIVELCOLOR, producto.getNivelColor().getCodigo())
	    								.addValue(PARAM_CODPROVEEDOR, producto.getProveedor().getCodProveedor())
	    								.addValue(PARAM_CODPRODUCTOPROVEEDOR, producto.getCodProductoProveedor())
	    								.addValue(PARAM_COMPONENTES, producto.getComponentes())
	    								.addValue(PARAM_CONSIGNACION, producto.getConsignacion())
	    								.addValue(PARAM_UNIONPRODUCTO, producto.getUnionProducto())
	    								.addValue(PARAM_OBSERVACIONES, producto.getObservaciones())
	    								.addValue(PARAM_ESTADO, producto.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    resultado += (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    // Instanciando variable para llamado de SP Eliminar componentes
	    SimpleJdbcCall llamarSPLimpiarContactos = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LIMPIAR_COMPONENTE_PRODUCTO);
	    // Agregar parametro codigo de producto
	    llamarSPLimpiarContactos.execute(new MapSqlParameterSource()
										     .addValue(PARAM_CODPRODUCTO, producto.getCodigo()));
	    
	    // Obteniendo lista de componentes a agregar
	    ListaComponente listaComponente = producto.getListaComponente();
	    
	    // Si existen componentes entonces registrarlos
	    if(listaComponente.getLista() != null){
		    // Instanciando variable para llamado de SP Agregar componentes
		    SimpleJdbcCall llamarSPComponentes = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_COMPONENTE_PRODUCTO);
	
		    for (Componente componente : listaComponente.getLista()){
			    // Estableciendo parametros de entrada al SP
			    SqlParameterSource parametrosConactos = new MapSqlParameterSource()
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODPRODUCTO, producto.getCodigo())
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODCOMPONENTE, componente.getCodigo())
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODPRODUCTOUNION, componente.getProducto()==null?null:componente.getProducto().getCodigo());
			    
			    // Establecer parametros y ejecutar SP
			    Map<String,Object> dataComponente = llamarSPComponentes.execute(parametrosConactos);
			    
			    // Obteniendo el total de filas afectadas al ejecutar SP
			    resultado += (Integer) dataComponente.get(TOTAL_FILAS_AFECTADAS);
		    }
	    }
	    return resultado > 0;
	}

	@Override
	public boolean eliminarProducto(Producto producto) {
		logger.info("eliminarProducto");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_ELIMINAR_PRODUCTO);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODPRODUCTO, producto.getCodigo());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado > 0;
	}

	@Override
	public boolean asociarProductoComponente(Producto producto){
		logger.info("asociarProductoComponente");
		
		int resultado = 0;
	    
	    // Obteniendo lista de componentes a agregar
	    ListaComponente listaComponente = producto.getListaComponente();
	    
	    // Si existen componentes entonces registrarlos
	    if(listaComponente.getLista() != null){
		    // Instanciando variable para llamado de SP
		    SimpleJdbcCall llamarSPComponentes = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_COMPONENTE_PRODUCTO);
	
		    for (Componente componente : listaComponente.getLista()){
			    // Estableciendo parametros de entrada al SP
			    SqlParameterSource parametrosContactos = new MapSqlParameterSource()
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODPRODUCTO, producto.getCodigo())
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODCOMPONENTE, componente.getCodigo())
						    								.addValue(PARAM_COMPONENTEPRODUCTO_CODPRODUCTOUNION, componente.getProducto()==null?null:componente.getProducto().getCodigo());
			    
			    // Establecer parametros y ejecutar SP
			    Map<String,Object> dataComponente = llamarSPComponentes.execute(parametrosContactos);
			    
			    // Obteniendo el total de filas afectadas al ejecutar SP
			    resultado += (Integer) dataComponente.get(TOTAL_FILAS_AFECTADAS);
		    }
	    }
	    
	    return resultado > 0;
	}

	@Override
	public ListaProducto obtenerProductoCodProv(Producto producto, Tienda tienda) {
		logger.info("obtenerProductoCodProv");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_OBTENER_PRODUCTO_CODPROV).
	    						  returningResultSet(LISTADO, new RowMapper<Producto>(){
									@Override
									public Producto mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
										final Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setDescripcion(rs.getString(DESCRIPCION));
								        producto.setPrecioVentaMinimo(rs.getDouble(PRECIOVENTAMINIMO));
								        producto.setPrecioVentaMaximo(rs.getDouble(PRECIOVENTAMAXIMO));
								    	producto.setAlto(rs.getDouble(ALTO));
								    	producto.setAncho(rs.getDouble(ANCHO));
								    	producto.setLargo(rs.getDouble(LARGO));
								    	producto.setUnidadMedida(rs.getString(UNIDADMEDIDA));
								    	producto.setObservaciones(rs.getString(OBSERVACIONES));
								    	
								    	NivelProducto nivelProducto = new NivelProducto();
								    	nivelProducto.setCodigo(rs.getInt(CODNIVELPROD));
								    	nivelProducto.setDescripcion(rs.getString(NIVEL_PRODUCTO_DESCRIPCION));
								    	producto.setNivelProducto(nivelProducto);
								    	
								    	NivelTipo nivelTipo = new NivelTipo();
								    	nivelTipo.setCodigo(rs.getInt(CODNIVELTIPO));
								    	nivelTipo.setDescripcion(rs.getString(NIVEL_TIPO_DESCRIPCION));
								    	producto.setNivelTipo(nivelTipo);
								    	
								    	NivelMaterial nivelMaterial =  new NivelMaterial();
								    	nivelMaterial.setCodigo(rs.getInt(CODNIVELMATERIAL));
								    	nivelMaterial.setDescripcion(rs.getString(NIVEL_MATERIAL_DESCRIPCION));
								    	producto.setNivelMaterial(nivelMaterial);
								    	
								    	NivelColor nivelColor = new NivelColor();
								    	nivelColor.setCodigo(rs.getInt(CODNIVELCOLOR));
								    	nivelColor.setDescripcion(rs.getString(NIVEL_COLOR_DESCRIPCION));
								    	producto.setNivelColor(nivelColor);
								    	
								    	Proveedor proveedor = new Proveedor();
								    	proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								    	proveedor.setRazonSocial(rs.getString(PROVEEDOR_RAZONSOCIAL));
								    	producto.setProveedor(proveedor);
								    	
								    	producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								    	producto.setComponentes(rs.getString(COMPONENTES));
								        
								    	producto.setCantidadDisponible(rs.getInt(CANTIDADDISPONIBLE));
								    	
								        producto.setEstado(rs.getString(ESTADO));
								        producto.setConsignacion(rs.getString(CONSIGNACION));
								        producto.setUnionProducto(rs.getString(UNIONPRODUCTO));
								        producto.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return producto;
								    }
	    						  }
								 );

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODPRODUCTOPROVEEDOR, producto.getCodProductoProveedor())
	    								.addValue(PARAM_CODTIENDA, tienda.getCodigo()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);
 
  	    // Obteniendo lista generada de ejecutar SP
 		@SuppressWarnings("unchecked")
 		List<Producto> listaProducto= (List<Producto>)data.get(LISTADO);
 	        
 		// Instanciando objeto ListaProducto
 		ListaProducto listaProductoResultado = new ListaProducto();
 	    // Estableciendo resultado al objeto listaProductoResultado
 		listaProductoResultado.setLista(listaProducto);
 	        
 	    if (logger.isDebugEnabled() && listaProductoResultado != null)
 	        {
 	            logger.debug("size=" + listaProductoResultado.size());
 	        }
 	    return listaProductoResultado;
	}
}
